<template>
  <div class="box-vertical body">
    <div class="box1">
      <el-card>
        <el-tabs v-model="tabName" tab-position="left" style="min-height:800px;">
          <el-tab-pane label="实验介绍" name="introduction">
            <div class="sub-title">
              <h3>
                名称
              </h3>
            </div>
            <div class="sub-artical">
              基于QEMU嵌入式Linux系统虚拟仿真环境的构建实验
            </div>
            <div class="sub-title sub-margin">
              实验目的
            </div>
            <div class="sub-artical">
              <p>
                嵌入式系统软件仿真实验具有通用、使用灵活、易于维护以及可扩展等优越特性，可以有效弥补硬件仿真实验在设备维护、资源占用、成本和实验内容等方面的不足。基于QEMU嵌入式Linux系统虚拟仿真实验项目，在没有开发板的情况下，也可以学习嵌入式Linux系统，这对计算机专业人才培养具有重要的意义。
              </p>
              <p>
                （1）从嵌入式系统实验教学运行角度，本实验项目主要为了解决学生实验受时间和场地的限制，解决实验资源有限与教学需求增长的矛盾。
              </p>
              <p>
                （2）从教学设备维护的角度，本实验项目主要为了解决嵌入式系统实验箱进行实验时故障率高和学校更新实验设备周期长的双重压力。
              </p>
              <p>
                （3）从学生能力培养角度，通过本实验项目，让学生熟练使用Linux操作系统、掌握Bootloader移植原理、掌握配置和编译内核的方法、掌握使用Busybox制作根文件系统的方法，了解开源软件QEMU内核模拟器的使用，从而掌握嵌入式Linux系统的开发流程。
              </p>
              <p>
                （4）采用开源仿真器QEMU设计了虚拟仿真教学实验，为嵌入式系统操作系统原理、嵌入式系统编程基础、Linux驱动开发以及嵌入式开发等教学内容提供良好支撑。
              </p>
              <p>
                本实验项目采用QEMU所具备的系统仿真能力，构建一种介于嵌入式操作系统和硬件设备之间的嵌入式虚拟仿真环境，来模拟各种硬件设备（如：Cortex-A9），使得学生在此环境中可以模拟各种硬件设备，从而获得一种不受时空限制，由一台个人笔记本就可以完成嵌入式操作系统开发，高效且廉价甚至免费的学习和开发环境，其架构如图2-1所示。
              </p>
              <p>
                <img src="../assets/images/description/struct.png" style="width: 400px;">
              </p>
              <p>
                在嵌入式操作系统实验课程中开展此项目，通过脚本语言代替复杂的图形界面和测试引擎，以开源的QEMU 模拟器作为Cortex-A9处理器的指令集仿真，构建嵌入式Linux系统虚拟仿真环境，旨在让学生通过认知实践、开放实验、项目设计等方式达到计算机专业嵌入式方向人才培养的目的。
              </p>
            </div>
            <div class="sub-title sub-margin">
              实验课时
            </div>
            <div class="sub-artical">
              <p>（1）实验所属课程所占课时： 32学时</p>
              <p>（2）该实验项目所占课时：6学时（可课外实验）</p>
            </div>
          </el-tab-pane>
          <el-tab-pane label="实验原理" name="theory">
            <div class="sub-title">
              <h3>实验原理</h3>
            </div>
            <div class="sub-artical">
              <h4>
                知识点一：Cortex-A9架构
              </h4>
              <p>
                ARM处理器大体上可以排序为：Cortex-A57处理器、Cortex-A53处理器、Cortex-A15处理器、Cortex-A12处理器、Cortex-A9处理器、Cortex-A8处理器、Cortex-A7处理器、Cortex-A5处理器、ARM11处理器、ARM9处理器、ARM7处理器，再往低的部分手机产品中基本已经不再使用，这里就不再介绍。
              </p>
              <p>
                <img src="../assets/images/description/ARMDevelopment.png">
              </p>
              <p>
                Cortex-A9处理器架构解析
              </p>
              <p>
                ARM Cortex-A9处理器隶属于Cortex-A系列，基于ARMv7-A架构，目前我们能见到的四核处理器大多都是属于Cortex-A9系列。
              </p>
              <p>
                <img src="../assets/images/description/Cortex-A9.png">
              </p>
              <p>
                Cortex-A9 处理器的设计旨在打造最先进的、高效率的、长度动态可变的、多指令执行超标量体系结构，提供采用序猜测方式执行的8阶段管道处理器，凭借范围广泛的消费类、网络、企业和移动应用中的前沿产品所需的功能，它可以提供史无前例的高性能和高能效。
              </p>
              <p>
                Cortex-A9 微体系结构既可用于可伸缩的多核处理器（Cortex-A9 MPCore多核处理器），也可用于更传统的处理器（Cortex-A9单核处理器）。可伸缩的多核处理器和单核处理器支持 16、32 或 64KB 4 路关联的 L1 高速缓存配置，对于可选的 L2 高速缓存控制器，最多支持 8MB 的 L2 高速缓存配置，它们具有极高的灵活性，均适用于特定应用领域和市场。
              </p>
              <p>
                应用案例：德州仪器OMAP 4430/4460、Tegra 2、Tegra 3、新岸线NS115、瑞芯微RK3066、联发科MT6577、三星Exynos 4210、4412、华为K3V2等。另外高通APQ8064、MSM8960、苹果A6、A6X等都可以看做是在A9架构基础上的改良版本。
              </p>
              <p>
                以上市面上流行的开发板都是物理意义上的开发板，而本项目实验要操作的是使用QEMU模拟一个ARM开发板。 在系统环境下输入： qemu-system-arm -M help  可以查看QEMU支持的ARM平台的开发板的型号，如下图3-4所示。结合一下网上的资料后发现有关 vexpress-a9 的资料和讨论最多，所以我们选择这个开发板来进行模拟。vexpress系列（全称Versatile Express Family）是ARM自己推出的开发板，主要是方便SOC厂商设计、验证和测试自己的SOC芯片设计用的。
              </p>
              <p>
                虽然我们要用软件模拟运行这个开发板，但硬件结构还是要了解的，这样才能做到知己知彼。由于vexpress的面向用户是SOC设计者，所以设计方法也很另类，采用了主板+子板的设计结构，主板提供各种外围接口，子板提供CPU运算。
              </p>
              <p>
                主板 Express uATX（或 V2M-P1）是 Versatile Express 系列中的第一款可用主板，其硬件结构如图3-3所示。它嵌在 uATX 大小的两件式漂亮塑料外壳内。活动式壳盖可以露出主板以便安装子板和连接测试设备。所有连接器和控制器都安装在后面板上。此主板有两组子板牛角连接器。它必须始终与处理器子板 Express板（其硬件外形结构如图3-4所示）配对使用以提供主系统处理器。可以添加可选的逻辑子板 Express 板以提供自定义 IP 开发和验证功能。
              </p>
              <p>
                <img src="../assets/images/description/uATX.png">
              </p>
              <p>
                处理器子板 Express 板在 Versatile™ Express 开发系统中提供主系统 CPU，外形如图3-4所示。处理器子板必须与提供电源、配置和外设连接的主板 Express uATX 板配对使用。处理器子板 Express 板与 Versatile 产品系列中的前代产品的不同之处在于，其内存和 LCD 控制器等高带宽外设是与 ARM 处理器一起在测试芯片中实现的。这会显示提升性能，使系统更适合进行软件基准测试并完全能运行 Debian Linux 等桌面操作系统。
              </p>
              <p>
                <img src="../assets/images/description/Express.png">
              </p>
              <p>
                <img src="../assets/images/description/systemTheory.png">
              </p>
              <p>
                系统原理架构图3-5和子板系统原理架构图3-6所示，虽然看上去比较复杂，但是我们用QEMU软件模拟的话把它当成一个整体。运行系统后和正常的开发板没什么区别。本项目也是用QEMU模拟运行vexpress-a9开发板。
              </p>
              <p>
                <img src="../assets/images/description/testChip.png" style="width: 400px;">
              </p>
              <h3>知识点二：QEMU模拟器</h3>
              <p>
                QEMU模拟器是一个开源的通用软件仿真器，使用动态翻译技术，可以在宿主机上模拟出另外一种体系结构客户机计算机系统，从而可以在宿主机上运行客户机操作系统和应用程序；QEMU既支持通用计算机体系结构，也支持ARM，MIPS，PowerPC，SPARC，ColdFire，MicroBlaze，Xtensa等多种嵌入式体系结构，其支持的ARM处理器数量有50多种；QEMU使用了多种优化技术，极大提高了仿真速度；QEMU自1.3.0版之后正式整合KVM，使其同时也成为一款优秀的虚拟机软件。
              </p>
              <p>
                QEMU 具有可扩展，可自定义新的指令集，开源并可移植，仿真速度快的优点。根据以上几点，可以选择使用QEMU 进行处理器的指令集仿真，通过建立一个虚拟硬件环境，使得目标系统运行在仿真环境中就好像运行在真实的物理环境一样，它使得构建全数字仿真测试平台成为可能, 图3-7是QEMU 的基本框架示意图。控制器主要由设备管理，中断处理，源文件读取和目标文件的缓存几部分组成，主要负责对目标代码的执行文件的加载，目标文件的缓存，对外设的管理以及对中断控制的仿真。翻译核心是对目标文件的二进制数据的反汇编，以及生成一一对应的且与平台无关的TCG 中间码，并将该TCG 中间码翻译成目标架构。
              </p>
              <p>
                <img src="../assets/images/description/QEMUStructure.png">
              </p>
              <p>
                本实验项目QEMU模拟器在主机上的安装如下命令：
              </p>
              <p>
                tyc@ubuntu:/$ sudo apt-get install qemu qemu-system qemu-utils
              </p>
              <p>
                tyc@ubuntu:/$ qemu-system-arm --version
              </p>
              <p>
                QEMU emulator version 2.11.1(Debian 1:2.11+dfsg-1ubuntu7.21)
              </p>
              <p>
                Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
              </p>
              <p>
                查看当前版本的Qemu工具支持的开发板列表如图3-8所示，它可以支持很多类型的开发板，如Cortex-A8和Cortex-A9处理器：
              </p>
              <p>
                tyc@ubuntu:/$ qemu-system-arm -M help
              </p>
              <p>
                <img src="../assets/images/description/QEMUSupport.png">
              </p>
              <h3>
                知识点三：云服务器
              </h3>
              <p>
                云服务器(Elastic Compute Service, ECS)是一种简单高效、安全可靠、处理能力可弹性伸缩的计算服务。其管理方式比物理服务器更简单高效。云服务器是云计算服务的重要组成部分，是面向各类互联网用户提供综合业务能力的服务平台。平台整合了传统意义上的互联网应用三大核心要素：计算、存储、网络，面向用户提供公用化的互联网基础设施服务。
              </p>
              <h4>
                虚拟化技术
              </h4>
              <p>
                虚拟化平台将1000台以上的服务器集群虚拟为多个性能可配的虚拟机(KVM)，对整个集群系统中所有KVM进行监控和管理，并根据实际资源使用情况灵活 分配和调度资源池。
              </p>
              <h4>
                分布式存储
              </h4>
              <p>
                技术原理：分布式存储用于将大量服务器整合为一台超级计算机，提供大量的数据存储和处理服务。分布式文件系统、分布式数据库允许访问共同存储资源，实现应用数据文件的IO共享。
              </p>
              <h4>
                资源调度
              </h4>
              <p>
                虚拟机可以突破单个物理机的限制，动态的资源调整与分配消除服务器及存储设备的单点故障,实现高可用性。当一个计算节点的主机需要维护时，可以将其上运行的虚拟机通过热迁移技术在不停机的情况下迁移至其他空闲节点，用户会毫无感觉。在计算节点物理损坏的情况也可以在3分钟左右将其业务迁移至其他节点运行，具有十分高的可靠性。
              </p>
              <h4>
                本项目用到的云服务器是阿里云服务器，配置如下图3-9所示：
              </h4>
              <p>
                <img src="../assets/images/description/serverConfiguration.png">
              </p>
              <h3>
                知识点四：交叉编译环境
              </h3>
              <p>
                交叉编译是嵌入式开发过程中的一项重要技术，简单地说，就是在一个平台上生成另一个平台上的可执行代码。交叉编译这个概念的出现和流行是和嵌入式系统的广泛发展同步的。我们常用的计算机软件，都需要通过编译的方式，把使用高级计算机语言编写的代码（比如C代码）编译（compile）成计算机可以识别和执行的二进制代码。交叉编译的主要特征是某机器中执行的程序代码不是由本机编译生成，而是由另一台机器编译生成，一般把前者称为目标机，后者称为主机。这是因为目标平台上不允许或不能够安装开发所需要的编译器，而又需要该编译器的某些特征；有时是因为目标平台上的资源贫乏，无法运行开发所需要的编译器；有时是因为目标平台还没有建立，连操作系统都没有，根本谈不上运行编译器。
              </p>
              <p>
                本项目实验环境Linux内核编译采用arm-eabi编译器，并统一了工作环境。安装交叉编译工具如下：
              </p>
              <p>tyc@ubuntu:/$ sudo apt-get update</p>
              <p>tyc@ubuntu:/$ sudo apt-get install gcc-arm-linux-gnueabi</p>
              <p>tyc@ubuntu:/$ sudo apt-get install g++-arm-linux-gnueabi</p>
              <p>tyc@ubuntu:/$ arm-linux-gnueabi-gcc –v</p>
              <p>······</p>
              <p>Thread model: posix</p>
              <p>gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1)</p>
              <h4>
                知识点五：Uboot启动代码
              </h4>
              <p>
                简单地说，本实验中u-boot是引导程序Bootloader，它是在操作系统内核运行之前运行的一段小程序。通过这段小程序，我们可以初始化硬件设备、建立内存空间的映射图，从而将系统的软硬件环境带到一个合适的状态，以便为最终调用操作系统内核准备好正确的环境。
              </p>
              <p>
                Bootloader（引导加载程序）是系统加电后运行的第一段代码，一般运行的时间非常短，但是对于嵌入式系统来说，这段代码非常重要。在我们的台式电脑当中，引导加载程序由BIOS（固件程序）和位于硬盘MBR中的操作系统引导加载程序（比如NTLOADER，GRUB和LILO）一起组成。在嵌入式系统当中没有像BIOS这样的固件程序，不过也有一些嵌入式CPU会在芯片内部嵌入一小段程序，一般用来将bootloader装进RAM中，有点类似BIOS，但是功能比BIOS弱很多。在一般的典型系统中，整个系统的加载启动任务全由bootloader来完成。在ARM中，系统上电或复位时通常从地址0x00000000处开始执行，而在这个位置，通常安排的就是系统的bootloader。通过这小段程序可以初始化硬件设备、建立内存空间映射图，从而将系统的软硬件环境设置到一个合适的状态！以为最终调用操作系统内核准备好正确的环境。
              </p>
              <p>
                <img src="../assets/images/description/BootloaderStartProcess.png">
              </p>
              <p>
                启动过程由BL0、BL1和BL2（BL 为BootLoader的简称）3部分代码实现如图3-10所示，其中BL0在出厂时已经被固化到64KB的iROM 中。S5PV210上电后首先执行BL0，该段代码主要负责一些简单的初始化工作，如关看门狗、初始化ICache等；然后BL0会根据硬件设置判断使用何种方式启动，并将BL1从启动设备（OneNand、Nand Flash、USB、UART、SD card等）拷贝到Internal SRAM 的BL1区中；最后BL0会比较一个校验值，如果相等则跳转到BL1中继续执行，否则转入其他启动方式。该校验值存在于BL1的头部，大小为１６字节。由于BL1的大小被限制为16KB，所以一般情况下BL1负责的工作也不多。BL1被执行后首先初始化系统时钟、内存、串口等，然后将BL2代码拷贝到InternalSRAM 的BL2区中并跳转执行。实际上SRAM 的BL2区的大小只有80KB，但很多情况下BL2代码的大小远远超过80KB，所以将BL2代码拷贝到SRAM 中意义不大。更好的做法是直接将BL2拷贝到容量更大的内存中，不过在拷贝之前一定要先初始化好系统时钟和内存。BL2是整个BooterLoad的主体部分，因此它需要完成更多的初始化工作，例如初始化网卡、Flash等，之后BL2读取操作系统镜像到内存中运行。一般把操作系统镜像放到Flash上，也可以放到SD卡上，根据具体的开发平台而定。
              </p>
              <p>
                U-Boot（Universal Bootloader ）是遵循GPL 条款的开放源码项目。它是从FADSROM、8xxROM、PPCBOOT 逐步发展演化而来。其源码目录、编译形式与Linux内核很相似，事实上，不少U-Boot 源码就是相应的Linux 内核源程序的简化，尤其是一些设备的驱动程序，这从U-Boot 源码的注释中能体现这一点。但是U-Boot 不仅仅支持嵌入式Linux 系统的引导，而且还支持NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS 等嵌入式操作系统。其目前要支持的目标操作系统是OpenBSD、NetBSD、FreeBSD、4.4BSD、Linux、SVR4、Esix、Solaris、Irix、SCO、Dell、NCR、VxWorks、LynxOS、pSOS、QNX、RTEMS、ARTOS。这是U-Boot 中Universal 的一层含义，另外一层含义则是U-Boot 除了支持PowerPC 系列的处理器外，还能支持MIPS、x86、ARM、NIOS、XScale 等诸多常用系列的处理器。这两个特点正是U-Boot项目的开发目标，即支持尽可能多的嵌入式处理器和嵌入式操作系统。就目前为止，U-Boot 对PowerPC 系列处理器支持最为丰富，对Linux 的支持最完善。
              </p>
              <p>
                当没有编译和开发板相关的程序，可以先使用一个编译好的U-Boot程序作为载体来运行一下看看效果，对模拟器模拟开发板有一个感性的认识。本项目实验采用官网https://ftp.denx.de/pub/u-boot/下载最新版u-boot-2017.05.tar.bz2源码包进行解压并在Makefile文件中加入arm和交叉编译器arm-linux-gnueabi-：
              </p>
              <p>ARCH？=arm</p>
              <p>CROSS_COMPILE ?= arm-linux-gnueabi-</p>
              <p>然后，用如下命令进行编译U-boot：</p>
              <p>#make vexpress_ca9x4_defconfig</p>
              <p>#make</p>
              <p>
                结果会在u-boot-2017.05文件夹下生成u-boot.bin等文件，如下图3-11 所示：
              </p>
              <p>
                <img src="../assets/images/description/U-Boot.png">
              </p>
              <p>
                在终端中执行下面的命令，来启动U-boot，前者不带图形界面，后者带图形界面，如图3-12所示。
              </p>
            <p>
              qemu-system-arm -M vexpress-a9 -m 256M -nographic -kernel u-boot
            </p>
            <p>
              或者
            </p>
            <p>
              qemu-system-arm -M vexpress-a9 -m 256M -serial stdio -kernel u-boot
            </p>
            <p>
              <img src="../assets/images/description/U-BootInterface.png" style="width: 600px;">
            </p>
            <h3>
              知识点六：Linux系统内核
            </h3>
            <p>
              内核是 Linux操作系统的核心，它管理所有线程、进程、资源和资源分配。与其它操作系统不同的是，Linux操作系统允许用户对内核进行重新设置。用户可以对内核进行“瘦身 ”，增加或消除对某些特定设备或子系统的支持。在开发嵌入式系统时，开发人员经常会减少系统对一些无用设备支持。将节省下来内存分配给各种应用软件。
            </p>
            <p>
              Linux内核对各种硬件和端口的支持要靠各种硬件驱动程序来实现。这些可驱动程序可以被直接写入内核，也可以针对某些特定硬件在需要时自动加载。通常情况下，可以被自动加载进内核的内核编码称为自动加载内核模块。
            </p>
            <p>
              Linux内核的设置是通过内核设置编辑器完成。内核设置编辑器可对每个内核设置变量进行描述，帮助用户决定哪些变量需要被清除，哪些需要写入内核，或者编成一个可加载内核模块在需要时进行加载。
            </p>
            <p>
              内核是为众多应用程序提供对计算机硬件的安全访问一部分软件，这种访问是有限的，并且内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的，所以内核通常提供一种硬件抽象的方法来完成这些操作。硬件抽象隐藏了复杂性，为应用软件和硬件提供了一套简洁，统一的接口，使程序设计更为简单。
            </p>
            <p>
              用户可以根据自己的需要编译内核。 本项目实验需要内核镜像到网站www.kernel.org下载最新的内核版本linux-4.4.207.tar.xz源码包进行配置与编译。
            </p>
            <p>解压linux-4.4.207.tar.xz</p>
            <p>tar -xvf linux-4.4.207.tar.xz</p>
            <p>cd linux-4.4.207/</p>
            <p>修改Makefile文件</p>
            <p>gedit Makefile</p>
            <p>ARCH = arm</p>
            <p>CROSS_COMPILE=arm-linux-gnueabi-</p>
            <p>编译内核、模块、dtb文件</p>
            <p>make vexpress_defconfig</p>
            <p>make vexpress_defconfig</p>
            <p>make zImage ‐j4</p>
            <p>make modules ‐j4</p>
            <p>make dtbs</p>
            <p>编译成功之后，在/linux-4.4.207/arch/arm/boot目录下生成内核zImage镜像如图3-所示。</p>
            <p>本项目实验使用U-boot引导内核镜像，需要将内核编译为uImage格式并指加载地址。编译之前还需要安装u-boot-tools ：</p>
            <p>#apt-get install u-boot-tools。</p>
            <p>编译时指定：</p>
            <p>#make LOADADDR=0x60003000 uImage -j4</p>
            <p>
              <img src="../assets/images/description/kernelImage1.png" style="width: 500px;">
            </p>
            <p>
              <img src="../assets/images/description/kernelImage2.png">
            </p>
            <h3>
              知识点七：构建基本文件系统
            </h3>
            <p>
              busybox是一个集成了一百多个最常用linux命令和工具的软件，他甚至还集成了一个http服务器和一个 telnet服务器，而所有这一切功能却只有区区1M左右的大小。我们平时用的那些Linux命令就好比是分立式的电子元件，而busybox就好比是一个集成电路，把常用的工具和命令集成压缩在一个可执行文件里，功能基本不变，而大小缺小很多倍，在嵌入式 linux应用中，busyboxx有非常广的应用。另外，大多数linux发行版的安装程序中都有busybox的身影，安装linux的时候按 ctrl+alt+F2就能得到一个控制台，而这个控制台中的所有命令都是指向busybox的链接。 busybox的小身材大作用特性，给制一张软盘的 小身材大作用特性，给制一张软盘的 小身材大作用特性，给制一张软盘的 linux带来了及大方便。
            </p>
            <p>
              busybox是标准Linux工具的一个单个可执行实现。 busybox包含了一些简单的工具，例如cat 和 echo，还包含了一些更大、更复杂的工具，例如 grep、find、mount以及 telnet。有些人将busybox称为 Linux工具里的瑞士军刀。简单说busybox 就好像是个大工具箱，它集成压缩了Linux的许多工具和命令，用户可以根据自己的需要定制一个busybox。
            </p>
            <p>
              Linux根文件系统包含了除内核以外的所有 linux系统在引导和管理时需要的工具，做为启动做为启动引导驱动，包含如下目录： bin，dev ， etc，home，lib，mnt，proc，sbin，usr ，var。还需要有一些基本的工具： sh ，ls ，cp ，mv……（位于/bin目录中）；必要的配置文件：inittab，rc，fstab……位于（ /etc目录中）；必要的设备文件： dev/tty*，/dev /console，/dev/men……（位于/dev目录中）； sh，ls 等工具必要的运行库： glibc。
              知识点八：NFS网络文件系统
            </p>
            <p>
              NFS（Network File System）是由 SUN公司开发 , 并于 1984 年推出， NFS 是一个 RPC service，它使我们能够达到档案的共享，它的设计是为了在不同系统间使用，所以它的通讯协议设计与主机及作业系统无关。当使用者想用远端档案时只要用 “mount”就可把remote档案系统挂接在自己的档案系统之下，使得远端的档案使用和 local机器的档案没两样。
            </p>
            <p>
              NFS至少包括两个主要的部分：一台服务器，以及至少一台客户机，客户机远程地访问保存在服务器上的数据。 要让这一切运转起来，需配置并行几个程序。
            </p>
            <p>
              服务器必须运行服务：
            </p>
            <table>
              <tr>
                <th>服务</th>
                <th>描述</th>
              </tr>
              <tr>
                <td>Nfsd</td>
                <td>NFS，为来自NFS客户端的请求服务。</td>
              </tr>
              <tr>
                <td>Mountd</td>
                <td>NFS挂载服务，处理nfsd（8）递交过来的请求。</td>
              </tr>
              <tr>
                <td>Rpcbind</td>
                <td>此服务允许NFS客户程序查询正在被NFS服务使用的端口</td>
              </tr>
            </table>
            <p>
              客户端同样运行一些进程，比如nfsiod，nfsiod处理NFS的请求。这是可选的，而且可以提高性能，对于普通和正确的操作来说并不是必须的。
            </p>
            <p>
              本项目实验平台使用busybox制作根文件系统，到https://busybox.net/downloads/下载最新的busybox源码包busybox-1.31.1.tar.bz2进行解压，并进入busybox-1.31.1目录修改Makefile文件，配置并编译busybox成静态库。
            </p>
            <p>
              #tar jxvf busybox-1.31.1.tar.bz2
            </p>
            <p>
              ARCH = arm
            </p>
            <P>
              CROSS_COMPILE = arm-linux-gnueabi-
            </P>
            <p>
              busybox配置，编译成静态库
            </p>
            <p>
              make menuconfig ‐> setting ‐> static library
            </p>
            <P>
              编译安装
            </P>
            <p>
              make
            </p>
            <p>
              make install
            </p>
            <P>
              注意：install的文件在_install目录下
            </P>
            <p></p>
            <p>
              出现下面的信息安装成功
            </p>
            <p>
              --------------------------------------------------
            </p>
            <p>
              You will probably need to make your busybox binary
            </p>
            <p>
              setuid root to ensure all configured applets will
            </p>
            <p>
              work properly.
            </p>
            <p>
              --------------------------------------------------
            </p>
            <p></p>
            <p>
              root@ubuntu:/home/tyc/busybox-1.31.1/_install# ls
            </p>
            <p>
              bin  lib  linuxrc  sbin  usr
            </p>
            <p></p>
            <h4>制作简易根文件系统</h4>
            <p>1、安装busybox</p>
            <p>将busybox编译生成的_install目录下的文件全部拷贝到rootfs/目录</p>
            <p># mkdir rootfs</p>
            <p># cd rootfs</p>
            <p># cp -rfd busybox-1.31.1/_install /* ./</p>
            <p>2、安装glibc库</p>
            <p>在根文件系统中添加加载器和动态库：</p>
            <p># mkdir rootfs/lib</p>
            <p># cp /usr/arm-linux-gnueabi/lib/* rootfs/lib/ -rfp</p>
            <p>3) 静态创建设备文件</p>
            <p># mkdir rootfs/dev</p>
            <p># cd rootfs/dev</p>
            <p># mknod -m 666 tty1 c 4 1</p>
            <p># mknod -m 666 tty2 c 4 2</p>
            <p># mknod -m 666 tty3 c 4 3</p>
            <p># mknod -m 666 tty4 c 4 4</p>
            <p># mknod -m 666 console c 5 1</p>
            <p># mknod -m 666 null c 1 3</p>
            <p>至此，简易版根文件系统就制作完成</p>
            <p></p>
            <h4>制作SD卡文件系统镜像</h4>
            <p>1) 生成一个空的SD卡镜像：</p>
            <p># dd if=/dev/zero of=rootfs.ext3 bs=1M count=32</p>
            <p>2) 将SD卡格式化为ext3文件系统：</p>
            <p># mkfs.ext3 rootfs.ext3</p>
            <p>3）将rootfs烧写到SD卡：</p>
            <p>#mount -t ext3 rootfs.ext3 /mnt -o loop</p>
            <p>#cp -rf rootfs/* /mnt/</p>
            <p>#sudo umount /mnt</p>
            <p></p>
            <p>
              QEMU与宿主机之间的通信机制：QEMU提供了四种网络通信模式：TAP、user、Sockets和VDE。利用user模式可以实现虚拟机和宿主机之间的通信且较为简单易行，在这种通信模式中，虚拟机处于10.0.2.*网段，该网段通过一个NAT服务器与外界通信，NAT服务器的地址是10.0.2.2，虚拟机的IP地址从10.0.2.15开始分配。
            </p>
            </div>
          </el-tab-pane>
          <el-tab-pane label="实验仪器设备" name="device">
            <div class="sub-title">实验仪器设备</div>
            <div class="sub-artical">
              <h4>实验使用环境</h4>
              <p>PC系统：Windows7、Windows10</p>
              <p>虚拟机：VMware-15.5</p>
              <p>虚拟机系统： ubuntu18.04</p>
              <p>模拟开发板：Cortex-A9架构的ARM</p>
              <div>（2）使用开发工具</div>
              <p>模拟器：Qemu-2.11.1</p>
              <p>主机系统：linux-4.4.207(Linux Kernel)</p>
              <p>启动代码：u-boot-2017.04</p>
              <p>制作文件系统：busybox-1.31.1</p>
              <p>交叉编译工具：arm- linux-gnueabi-gcc 7.4.0</p>
            </div>
            <div class="sub-title sub-margin">预设参数</div>
            <div class="sub-artical">
              <p>本实验项目充分体现虚实结合的理念，在嵌入式Linux系统虚拟仿真环境中设置了以下实验参数供学生使用：</p>
              <ul>
                <li>qemu-system-arm：ARM结构仿真</li>
                <li>-M vexpress-a9：模拟Cortex-A9开发板</li>
                <li>-m 512M：单板运行物理内存为512M</li>
                <li>-kernel：告诉qemu单板运行时内核镜像的位置</li>
                <li>-append "console=tty0" 内核启动参数，内核vexpress单板运行，串口设备是tty0</li>
              </ul>
              <p>脚本启动界面参数设置：</p>
              <ul>
                <li>setenv ipaddr 192.168.110.100; setenv netmask 255.255.255.0; setenv serverip 192.168.110.129; setenv bootargs "console=ttyAMA0 root=/dev/mmcblk0 init=/linuxrc rw rootwait"</li>
                <li>
                  tftp 0x60000000 uImage; tftp 0x70000000 vexpress-v2p-ca9.dtb; fdt addr 0x70000000; bootm 0x60000000 - 0x70000000
                </li>
              </ul>
            </div>
          </el-tab-pane>
          <el-tab-pane label="实验教学方法" name="method">
            <div class="sub-title">实验教学方法</div>
            <div class="sub-artical">
              <ul>
                <li>
                  <h4>教学方法</h4>
                  <p>
                    本实验项目的教学设计实行基于问题、项目驱动的自主式学习，对学生具有挑战度。通过提出问题，布置实验任务，让学生利用课外大量时间在个人的pc机上搭建嵌入式系统虚拟实验环境，其中会碰到各种各样的问题和疑难杂症，必须花大量时间查找资料反复实验，从逐步解决问题当中掌握嵌入式系统相关的基本知识和方法，还可以以基本知识和方法为起点，进一步拓展、探索新的知识和方法，包括涉及本学科前沿和跨学科的知识和方法。
                  </p>
                  <p>
                    本项目的虚拟仿真环境可以指导学生在自己的个人计算机上建立一个仿真开发环境，可以调试并运行学生自己编写的程序。在讲解嵌入式系统GUI编程时，希望学生可以动手搭建自己的GUI开发环境，自己开发GUI程序，会使用Qt或其他工具，QEMU可模拟LCD外设，在模拟出的LCD上显示图形化界面，可激发学生学习兴趣，这些实验也适合在课外完成，使学生有充足的时间完成设计与调试。此外，在讲解嵌入式Linux驱动程序开发、网络编程等内容时，也可以使用QEMU设计教学实验、课堂演示案例等，提升教学效果。还可以设计系统性、综合性实验，帮助学生掌握嵌入式系统软件开发的方法和流程。
                  </p>
                </li>
                <li>
                  <h4>
                    实施效果
                  </h4>
                  <p>
                    首先，本项目使用一台笔记本或微型计算机就能搭建好嵌入式系统虚拟仿真环境，不受空间与场地的限制，学生可随时随地进行实验，对知识点不断学生和反复演练，深刻地掌握嵌入式系统的相关理论和开发技能。
                  </p>
                  <p>
                    其次，本项目可以定时更新升级，确保了仿真平台始终与市场上的更换速度保持一致，确保了实验设备的先进性；开拓了学生的视野，激发了学生的实验兴趣，显著提升了学生的创新精神和实践能力。
                  </p>
                  <p>
                    最后，大量综合型及创新型实验项目得以在该虚拟仿真环境中开展，可激发学生学习兴趣，这些实验也适合在课外完成，使学生有充足的时间完成设计与调试。
                  </p>
                  <p>
                    以项目驱动为导向的互动教学方法，增加了学生学习的主动性，学生带着项目学习，在项目实施的过程中解决问题。在互动讨论和文献资料检索的过程中，增加了对重要知识点的总结和扩展训练。
                  </p>
                </li>
              </ul>
            </div>
          </el-tab-pane>
          <el-tab-pane label="实验考核要求" name="test">
            <div class="sub-title">
              实验考核要求
            </div>
            <div class="sub-artical">
              <ul>
                <li>
                  <h4>
                    实验方法描述：
                  </h4>
                  <p>
                    “基于QEMU嵌入式Linux系统虚拟仿真环境的构建实验”主要包括以下三部分：一是实验预习与文献检索；二是主机上编写应用程序进行交叉编译；三是目标机上启动虚拟仿真环境，运行应用程序，并观察实验结果。
                  </p>
                </li>
                <li>
                  <h4>
                    学生交互性操作步骤说明
                  </h4>
                  <h5>（一）实验预习与文献检索</h5>
                  <p>
                    1. 自主预习，查阅文献，了解实验目的、实验原理、QEMU模拟器的使用说明、实验步骤等；
                  </p>
                  <p>
                    2. 完成切题的文献检索，了解嵌入式系统发展的科技前沿，考察学生对实验内容掌握的深度与广度。
                  </p>
                  <h5>
                    （二）主机上编写应用程序进行交叉编译
                  </h5>
                  <p>
                    (1).设置工作环境：
                  </p>
                  <p>
                    由于交叉编译器arm-linux-gnueabi-gcc安装/usr/bin目录下，设置交叉编译的工作环境，执行命令如下：
                  </p>
                  <P>
                    export PATH=/usr/ bin:$PATH
                  </P>
                  <p>
                    (2)．部署实验源码，并完成交叉编译：
                  </p>
                  <p>
                    应用程序以编写一个多进程process.c为例（其它应用程序或驱动程序在此虚拟环境下调试运行方法类似），用vi编辑器编辑：
                  </p>
                  <p>vi process.c</p>
                  <p>#include &lt;stdio.h></p>
                  <p>#include &lt;fcntl.h></p>
                  <p>#include &lt;unistd.h></p>
                  <p>#include &lt;stdlib.h></p>
                  <p>#include &lt;sys/types.h></p>
                  <p>#include &lt;sys/wait.h></p>
                  <p>int main(int argc, char **argv)</p>
                  <p>{</p>
                  <p>int stat;</p>
                  <p>pid_t child;</p>
                  <p>printf("\nTry to create new process.\n");</p>
                  <p>child = fork();</p>
                  <p>switch(child)</p>
                  <p>{</p>
                  <p>case -1:</p>
                  <p>perror("fork.\n");</p>
                  <p>exit(EXIT_FAILURE);</p>
                  <p>case 0:</p>
                  <p>printf("This is child.\n");</p>
                  <p>printf("\tchild pid is %d\n", getpid());</p>
                  <p>printf("\tchild ppid is %d\n", getppid());</p>
                  <p>exit(EXIT_SUCCESS);</p>
                  <p>default:</p>
                  <p>waitpid(child, &stat, 0);</p>
                  <p>printf("This is parent.\n");</p>
                  <p>printf("\tparent pid is %d\n", getpid());</p>
                  <p>printf("\tparent ppid is %d\n", getppid());</p>
                  <p>printf("\tchild exited with %d\n", stat);</p>
                  <p>}</p>
                  <p>exit(EXIT_SUCCESS);</p>
                  <p>}</p>
                  <p>主机编译执行如下：</p>
                  <p>gcc -Wall -g process.c -o process-host</p>
                  <p>编译通过生成可执行程序process-host。</p>
                  <p>主机上进行交叉编译执行如下：</p>
                  <p>arm-linux-gnueabi-gcc process.c -o process-arm</p>
                  <p>编译通过生成可执行程序process-arm。</p>
                  <p>在阿里云服务器主机上运行可执行程序process-host和process-arm，如图7-1显示process-host可执行，process-arm不能执行。process-arm需要在宿主机虚拟仿真环境下运行。</p>
                  <p><img src="../assets/images/description/processHostAndProcessArm.png"> </p>
                  <p>3.拷贝可执行程序process-arm拷贝到rootfs目录下的home目录</p>
                  <p>将交叉编译生成的可执行程序process-arm拷到rootfs目录下的home目录。</p>
                  <p>4.将rootfs烧写到SD卡：</p>
                  <p>#mount -t ext3 rootfs.ext3 /mnt -o loop</p>
                  <p>#cp -rf rootfs/* /mnt/</p>
                  <p>#sudo umount /mnt</p>
                  <p> (三) 启动虚拟仿真环境，运行应用程序</p>
                  <p>
                    启动虚拟仿真环境有两种方法，一种是直接启动内核并挂载rootfs文件系统；另一种是使用U-boot引导Linux内核镜像来启动。具体操作：登录阿里云服务器，并切换到home目录下，该目录下有三个仿真目录QEMU_test、QEMU_tftp、QEMU_qt_test。仿真目录QEMU_test中的脚本文件boot-nographic.sh是用于直接启动内核并挂载rootfs文件系统，要仿真的程序需要先放到rootfs目录下的home目录中，然后将rootfs烧写到SD卡。QEMU_tftp是在无图形界面的情况下，通过tftp协议传输文件和NFS网络文件系统创建共享目录来进行仿真操作；QEMU_qt_test仿真目录是带qt图形界面的，要仿真的程序操作跟QEMU_test目录类似，一般用于qt5.12编写的程序通过交叉编译的程序进行仿真。下面介绍这两种方法的仿真操作。
                  </p>
                  <p>
                    1、启动内核并挂载rootfs
                  </p>
                  <p>登录阿里云服务器，并切换到home目录下，该目录下有仿真目录QEMU_test，运行脚本文件boot-nographic.sh（不带图形界面），boot.sh（带图形界面）。</p>
                  <p>脚本文件boot-nographic.sh具体内容如下：</p>
                  <p>#! /bin/bash</p>
                  <p>qemu-system-arm \</p>
                  <p>-M vexpress-a9 \</p>
                  <p>-m 512M \</p>
                  <p>-kernel zImage \</p>
                  <p>-dtb vexpress-v2p-ca9.dtb \</p>
                  <p>-append "root=/dev/mmcblk0 rw console=ttyAMA0" \</p>
                  <p>-nographic \</p>
                  <p>-sd rootfs.ext3</p>
                  <p>参数介绍：</p>
                  <p>qemu-system-arm：ARM结构仿真</p>
                  <p>-M vexpress-a9 ：模拟Cortex-A9开发板</p>
                  <p>-m 512M ：单板运行物理内存为512M</p>
                  <p>-kernel zImage ：告诉qemu单板运行时内核镜像是哪个在哪里</p>
                  <p>-dtb vexpress-v2p-ca9.dtb ：告诉qemu单板的设备树</p>
                  <p>-append "root=/dev/mmcblk0 rw console=ttyAMA0" ：内核启动参数，内核vexpress单板运行，串口设备是ttyAMA0</p>
                  <p>-nographic ：不使用图形界面，只使用串口</p>
                  <p>-sd rootfs.ext3：挂载根文件系统为sd卡</p>
                  <p>启动该脚本进入虚拟仿真环境界面如图7-2如下：</p>
                  <p>root@iZbp1edvty8pjib08ackmuZ:/home/QEMU_test# ./boot-nographic.sh</p>
                  <p>
                    <img src="../assets/images/description/temp1.png">
                  </p>
                  <p>
                    <img src="../assets/images/description/temp2.png">
                  </p>
                  <p>跳出这个界面，点击“否”（会跳出两次，两次都点击“否”）</p>
                  <p>
                    <img src="../assets/images/description/temp3.png">
                  </p>
                  <p>
                    在虚拟仿真环境启动界面里，之前把交叉编译的可行性程序放到rootfs/home/目录下的进程文件随着内核和文件系统的启动直接加载到仿真环境。此时，进入到/home/process-embedded目录下，我们会看到之前经过交叉编译器编译的可行性文件process-arm，对他进行仿真操作如图7-3所示，运行结果跟之前主机上运行结果比较，发现进程号是不一样的，因为在不同的平台下。
                  </p>
                  <p>
                    2、用U-boot引导加载Linux内核镜像
                  </p>
                  <p>
                    <img src="../assets/images/description/temp4.png">
                  </p>
                  <p>
                    在前面的实验中，我们都是通过QEMU仿真直接运行Linux内核。而在实际的嵌入式系统中都是通过BootLoader加载Linux镜像，然后再去运行。
                  </p>
                  <p>
                    嵌入式BootLoader，功能类似PC中的BIOS，用以检测硬件是否正常。加载操作系统镜像到RAM，设置不同启动方式：
                  </p>
                  <ul>
                    <li>
                      <p>
                        1)	NOR/NAND Flash启动
                      </p>
                    </li>
                    <li>
                      <p>
                        2)	从SD卡启动
                      </p>
                    </li>
                    <li>
                      <p>3)	BootLoader从网络加载内核启动</p>
                      <p>下面将介绍QEMU从U-boot加载镜像然后启动。使用U-boot引导内核镜像的前提：需要将内核编译为uImage格式，并指定uImage的加载地址。编译时指定：</p>
                      <p>$ make LOADADDR=0x60003000 uImage -j4</p>
                      <p>具体操作步骤：</p>
                      <p>同样需要通过账号和密码登录阿里云服务器，并切换到home目录下，该目录下有仿真目录QEMU_tftp，运行脚本文件uboot_boot.sh（不带图形界面），boot.sh（带图形界面）。脚本文件详细内容如下：</p>
                      <p>#!/bin/bash</p>
                      <p>qemu-system-arm \</p>
                      <p>-M vexpress-a9 \</p>
                      <p>-kernel u-boot \</p>
                      <p>-nographic \</p>
                      <p>-m 512M \</p>
                      <p>-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \</p>
                      <p>-sd rootfs-qt5-12-1.ext3</p>
                      <p>参数说明：</p>
                      <p>qemu-system-arm ：ARM结构仿真</p>
                      <p>-M vexpress-a9 ：模拟Cortex-A9开发板</p>
                      <p>-kernel u-boot ：告诉qemu单板运行时内核镜像由u-boot引导</p>
                      <p>-nographic ：不使用图形界面，只使用串口</p>
                      <p>-m 512M ：单板运行物理内存为512M</p>
                      <p>-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 ：通过虚拟网络接口传输内核镜像和设备树文件</p>
                      <p>-sd rootfs-qt5-12-1.ext3：挂载根文件系统（带qt）为sd卡</p>
                      <p>https://www.jianshu.com/p/91baa4d140a2</p>
                      <p>https://www.cnblogs.com/wyzhou/p/9286864.html</p>
                      <p>运行脚本文件：</p>
                      <p>root@iZbp1edvty8pjib08ackmuZ:/home/QEMU_tftp# ./uboot_boot.sh</p>
                      <p><img src="../assets/images/description/temp5.png" style="width: 500px;"></p>
                      <p><img src="../assets/images/description/temp6.png" style="width: 400px;"></p>
                      <p>跳出这个界面，点击“否”（会跳出两次，两次都点击“否”）</p>
                      <p>倒计时3秒钟，按回车键，进入到u-boot启动界面如图7-4所示。</p>
                      <p><img src="../assets/images/description/temp7.png"></p>
                      <p>在这个界面下，需要设置如下参数如图7-5所示。</p>
                      <p>setenv ipaddr 172.19.164.100; setenv netmask 255.255.240.0; setenv serverip 172.19.164.196; setenv bootargs "console=ttyAMA0 root=/dev/mmcblk0 init=/linuxrc rw rootwait"</p>
                      <p>tftp 0x60000000 uImage; tftp 0x70000000 vexpress-v2p-ca9.dtb; fdt addr 0x70000000; bootm 0x60000000 - 0x70000000</p>
                      <p>参数说明：</p>
                      <p>setenv ipaddr 172.19.164.100：设置虚拟仿真环境嵌入式Linux系统的IP地址</p>
                      <p>setenv netmask 255.255.240.0：设置虚拟仿真环境嵌入式Linux系统的子网掩码</p>
                      <p>setenv serverip 172.19.164.196：设置主机上（阿里云服务器上ubuntu系统里私有IP地址）IP地址</p>
                      <p>setenv bootargs "console=ttyAMA0 root=/dev/mmcblk0 init=/linuxrc rw rootwait"：设置从串口启动，根文件系统从设备节点sd卡启动</p>
                      <p>tftp 0x60000000 uImage：uboot通过tftp指定地址加载uImage</p>
                      <p>tftp 0x70000000 vexpress-v2p-ca9.dtb：uboot通过tftp指定地址加载dtb文件</p>
                      <p><img src="../assets/images/description/temp8.png" style="width: 600px;"></p>
                      <p>参数设置好之后，虚拟仿真环境就启动起来了，如图7-6所示。</p>
                      <p><img src="../assets/images/description/temp9.png"></p>
                      <p>主机与嵌入式虚拟开发板之间设置共享目录如图7-7所示。这里主机必须支持NFS服务。实验平台上，我们设置主机的共享目录是/home/experiment，嵌入式虚拟开发板共享目录是/home，这两个目录构成了一个共享通道，在主机上经过交叉编译的可执行程序放入到/home/experiment目录下，在嵌入式虚拟开发板共享目录是/home下也能看得到：</p>
                      <p>tyc@vexpress:/ # ifconfig eth0 172.19.164.101 up</p>
                      <p>tyc@vexpress:/ # route add default gw 172.19.164.1</p>
                      <p>tyc@vexpress:/ # mount -t nfs -o nolock 172.19.164.196:/home/experiment /home</p>
                      <p>配置说明：在嵌入式虚拟开发板上设置ifconfig eth0 172.19.164.101 up，主要是让主机与虚拟开发板处于同一个局域网段172.19.164，并通过NFS服务去挂载。</p>
                      <p><img src="../assets/images/description/temp10.png"></p>
                      <p>在虚拟仿真环境下，运行process-arm，可以得到如下结果如图7-8所示。但是运行process-host就运行不了了。仿真成功。</p>
                      <p><img src="../assets/images/description/temp11.png"></p>
                    </li>
                  </ul>
                </li>
              </ul>
            </div>
          </el-tab-pane>
          <el-tab-pane label="实验结果与结论要求" name="result">
            <div class="sub-title">
              实验结果与结论要求
            </div>
            <div class="sub-artical">
              <p>（1）是否记录每步实验结果：x是 √否</p>
              <p>（2）实验结果与结论要求：√实验报告 √心得体会 其他：实验结果讨论</p>
              <p>其他描述：扩展实验设计与实施</p>
            </div>
            <div class="sub-title sub-margin">
              考核要求
            </div>
            <div class="sub-artical">
              <p>考核主要通过以下四个方面：</p>
              <ol>
                <li>实验预习：考察学生预习报告内容深度与广度。</li>
                <li>实验成果：检查实验成果的完成地难易度，工作量是否饱满，同时现场答辩知识技能的掌握程度。</li>
                <li>实验报告：检查实验报告的完整性、正确性和逻辑性，代码量。</li>
                <li>创新能力：实验演示结果及学生对实验结果的体会深度。</li>
              </ol>
            </div>
            <div class="sub-title sub-margin">
              面向学生要求
            </div>
            <div class="sub-artical">
              <ol>
                <li>
                  <p>专业与年级要求</p>
                  <p>计算机专业大三学生</p>
                </li>
                <li>
                  <p>基本知识和能力要求</p>
                  <p>学生利用这样设计的虚拟仿真环境开展实验，不仅可以完成验证性实验，验证本专业的基本知识和方法，还可以以基本知识和方法为起点，进一步拓展、探索新的知识和方法，包括涉及本学科前沿和跨学科的知识和方法。</p>
                </li>
              </ol>
            </div>
            <div class="sub-title sub-margin">
              实验项目应用及共享情况
            </div>
            <div class="sub-artical">
              <ol>
                <li>本校上线时间 ：未上线</li>
                <li>已服务过的本校学生人数：70人</li>
                <li>是否纳入到教学计划：√是  x否</li>
              </ol>
            </div>
          </el-tab-pane>
        </el-tabs>
      </el-card>
    </div>
  </div>
</template>

<script>
    export default {
        name: "Description",
        data(){
          return {
            tabName: 'introduction'
          }
        },
        created:function(){
          let data = this.$data;
          let that = this;
          console.log(this.$route.params);
          let position = this.$route.params.position;
          if(position!=null){
            data.tabName = position;
          }
        }
    }
</script>

<style scoped>
  a:hover{
    cursor: pointer;
  }

  .body{
    width: 100%;
    height: 100%;
    background-color: #f2f2f2;
  }

  .box1{
    width: 1000px;
    height: 100%;
    box-sizing: border-box;
    padding: 20px;
    min-height: 1000px;
  }
</style>
